package com.plter.controls.plter
{
	import flash.events.ContextMenuEvent;
	import flash.events.Event;
	import flash.events.FocusEvent;
	import flash.events.KeyboardEvent;
	import flash.system.Capabilities;
	import flash.text.TextField;
	import flash.text.TextFieldType;
	import flash.ui.ContextMenu;
	import flash.ui.ContextMenuItem;
	import flash.ui.Keyboard;
	import flash.utils.setTimeout;

	public class PTextField extends TextField
	{
		/**
		 * The undo string stack
		 */
		private var _undoVec:Vector.<String>=new Vector.<String>;

		/**
		 * The redo string stack
		 */
		private var _redoVec:Vector.<String>=new Vector.<String>;

		/**
		 * 初始化时的文本内容
		 */
		private var initContentText:String="";

		/**
		 * The undo contextitem
		 */
		private var undoItem:ContextMenuItem=new ContextMenuItem("撤销", false, false);

		public function PTextField()
		{
			super();

			this.addEventListener(Event.CHANGE, onTextChange);
			this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			this.addEventListener(FocusEvent.FOCUS_IN, onFocusIn);
			undoItem.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT, selectMenuItem);

			buildContextMenu();
		}


		/**
		 *
		 * Build the context menu,add undo menu item
		 */
		private function buildContextMenu():void
		{
			var customContextMenu:ContextMenu=new ContextMenu;

			switch (Capabilities.language)
			{
				case "zh-CN":
					undoItem.caption="撤销";
					break;
				default:
					undoItem.caption="Undo(Ctrl+z)";
			}
			customContextMenu.customItems.push(undoItem);
			customContextMenu.clipboardMenu=true;
			this.contextMenu=customContextMenu;
		}

		private function selectMenuItem(event:ContextMenuEvent):void
		{
			switch (event.target)
			{
				case undoItem:
					undo();
					break;
			}
		}

		private function onTextChange(event:Event):void
		{
			if (this.editable)
			{
				undoVecPush(super.text);
			}
		}

		private function undoVecPush(value:String):void
		{
			_undoVec.push(super.text);
			this.undoItem.enabled=true;

			if (_redoVec.length)
			{
				_redoVec.splice(0, _redoVec.length);
			}
		}

		public function undo():void
		{
			if (_undoVec.length > 0)
			{
				var popValue:String=_undoVec.pop();
				_redoVec.push(popValue);

				if (popValue != super.text)
				{
					super.text=popValue;
				}
				else if (_undoVec.length)
				{
					super.text=_undoVec.pop();
					_redoVec.push(super.text);
				}
				else
				{
					super.text=initContentText;
				}
			}
			else
			{
				if (super.text != initContentText)
				{
					super.text=initContentText;
				}
			}

			ifEnableUndoMenuItem();
		}

		public function redo():void
		{
			if (_redoVec.length)
			{
				var popValue:String=_redoVec.pop();
				_undoVec.push(popValue);

				if (popValue != super.text)
				{
					super.text=popValue;
				}
				else
				{
					super.text=_redoVec.pop();
					_undoVec.push(super.text);
				}
			}

			ifEnableUndoMenuItem();
		}

		/**
		 * Enable the undo menu item by actual situation
		 */
		private function ifEnableUndoMenuItem():void
		{
			this.undoItem.enabled=_undoVec.length || super.text != initContentText;
		}

		private function onKeyDown(event:KeyboardEvent):void
		{
			if (this.editable)
			{
				super.type=event.ctrlKey ? TextFieldType.DYNAMIC : TextFieldType.INPUT;
			}

			if (!event.ctrlKey)
			{
				return;
			}

			switch (event.keyCode)
			{
				case 90: //z
					undo();
					break;
				case 89: //y
					redo();
					break;
			}
		}

		private function onKeyUp(event:KeyboardEvent):void
		{
			switch (event.keyCode)
			{
				case Keyboard.CONTROL:
					if (this.editable)
					{
						super.type=TextFieldType.INPUT;
					}
					break;
			}
		}

		private function onFocusIn(event:FocusEvent):void
		{
			if (this.editable)
			{
				super.type=TextFieldType.INPUT;
			}
		}

		public override function set type(value:String):void
		{
			super.type=value;
			_editable=value == TextFieldType.INPUT;
			if(!editable){
				if(_undoVec.length){
					_undoVec.splice(0,_undoVec.length);
				}
				if(_redoVec.length){
					_redoVec.splice(0,_redoVec.length);
				}
				ifEnableUndoMenuItem();
			}
		}

		public override function get type():String
		{
			return super.type;
		}

		public override function set text(value:String):void
		{
			if (editable)
			{
				initContentText=value;
				_undoVec.splice(0, _undoVec.length);
				_redoVec.splice(0, _redoVec.length);
				ifEnableUndoMenuItem();
			}
			super.text=value;
		}

		private var _editable:Boolean=false;

		public function set editable(value:Boolean):void
		{
			this.type=value ? TextFieldType.INPUT : TextFieldType.DYNAMIC;
		}

		public function get editable():Boolean
		{
			return _editable;
		}

		public function dispose():void
		{
			this.removeEventListener(Event.CHANGE, onTextChange);
			undoItem.removeEventListener(ContextMenuEvent.MENU_ITEM_SELECT, selectMenuItem);
			this.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			this.removeEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			this.removeEventListener(FocusEvent.FOCUS_IN, onFocusIn);
		}
	}
}